<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
       "http://www.w3.org/TR/xhtml11/DTD/xhtml11-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<title>
		标注算法
	</title>
	<style type="text/css">
		@import url("../css/function.css");
	</style>
</head>
<body>
	<h1 id='htitle'>
		标注算法
	</h1>
<a href="../index.html">返回主索引</a>
<hr /><!--"----------------------------------------"-->
<p>标注本身就是很专业很费脑子的一块，要做得好很难。所以做这块，我也是怵怵的。虽然九形初衷并不是在渲染作图之类的“面子”功夫上（当然这面子功夫不是很表面的技术啦，不过这种功夫我想我这种个人玩玩的永远赶不上ESRI和MapInfo），但是至少现在先做个样子吧，不然九形渲染这块实在太弱了，而且这块也很基本很常用，做出来也会方便点，好看点（最近玩诛仙，发现里面的地图做得不错，渲染和标注都挺古典。呵呵，我玩3D游戏感觉在做虚拟现实，满脑子跑代码，至于练级倒不是很在意。哈哈，跑题^_^）。做是做，但是是硬着头皮做，我不敢说我做得很好。后面有谁觉得不好的，大可以做个自己的品牌出来。
</p>
<p>自动注记规则本身就很复杂，要考虑很多因素。简单的说：一是要<b>注意从属关系</b>。应容易确定注记与被注记目标之间的所属关系, 不会与附近注记或其它目标发生混淆。二是要<b>注意“避让”原则</b>。注记应避开重要地物, 即不能压盖重要地物, 尤其不能压盖同种颜色的其它地物。三是要<b>注意习惯原则</b>。注记的字位、字序、排列方式要符合读图的习惯。而一般说业内人士对点状注记遵循以下原则:
</p>
<ol type="1"> 
<li>注记的分布以正右为先, 其次分别是正上、正左、正下, 再其分别是右上、左上、左下、右下等位置, 分布形式多呈水平.</li>
<li> 注记不能压盖被注记要素和其它点状要素.</li>
<li> 注记不能压盖同颜色的重要的线状地物, 如铁路与干线公路; 尽量不要压盖同颜色的其余线状地物, 如机耕路、乡村路、小路等. 与相同颜色等级、较低的线状要素相压盖时, 线状要素要在此断开.</li>
<li>注记与注记之间彼此不能压盖.</li>
<li>注记最好要与被注记的点状地物在境界的同侧, 且不能压盖境界. 这些是进行注记时应具备的基本知识.</li>
</ol>
<p>这里还有提到自动配置排列需要考虑因素。
</p>
<ol type="1">
	<li><h4>根据几何特征类型分层处置</h4>
	根据几何特征类型分层处置在进行注记时, 区别不同的地物类型意义不大, 但是, 由于地物几何特征的不同, 自动处理的算法、思路、数据的存贮结果会有很大的不同, 这意味着, 不同特征类型的要素会有完全不同的处理方法。例如, 点要素的注记通常是环绕点位进行, 主要考虑与注记点结合的紧密程序, 与其他注记是否冲突、压盖; 而线要素的注记则以沿线要素形状分布为宜, 当然也要考虑与其他注记冲突和与其余要素压盖的问题。面状要素又可以分为面团状(如居民地)、小面积面状、大面积面状和条形面状。各种情况要进行不同的处理, 面团状要求沿着外轮廓线注记; 小面积面状宜作点状要素处理; 大面积面状需要沿主骨架线注记; 条形面状宜沿着条状的外沿形状注记。因此, 注记配置原则应考虑分成点、线、面3种不同的几何类型分别进行处理。</li>
	<li><h4>点、线、面注记的优先级</h4>
在地图的注记(如全要素地形图的注记)中, 由于涉及到多种特征类型的多种要素, 因此有一个综合平衡和优先考虑的问题。一般而言, 点、线、面注记的先后顺序应该是先点、后线、再面。当然, 根据不同的输出要求, 可以有不同的优先级的规定。但是, 需要明确的是, 不同优先级的确定将决定不同的地图注记结果。
</li>
<li><h4>冲突避让优先级</h4>
理想的注记位置是所有居民地注记都分布在居民点的正右方, 所有线状注记都分布在河流右侧或上侧居中且均匀分布, 面状注记分布在居民点的周围居右且结合紧密。由于地理要素密集, 按理想状态安排, 注记冲突无法避免, 通过调整注记位置来解决冲突是自动注记的主要任务。谁避让谁存在一个权衡取舍问题, 这时一般要由地物的重要程度来决定。例如, 省、地、市政府所在地要比一般居民点更重要, 一般居民点要避让, 这可以根据地物本身的等级属性予以考虑。因此, 在进行自动注记之前, 需根据应用的要求对冲突避让优先级先给出一个综合的考虑。
</li>
<li><h4>压盖避让优先级</h4>
由于地图上地理要素密集, 注记对地物完全不压盖是不可能的。因此, 在处理压盖的问题上,就存在着轻重先后的问题。例如, 在考虑全要素地形图居民地注记问题时, 居民地注记就可能对河流、道路形成压盖, 而且某些地域由于河网、道路的密集, 要想完全消除压盖是不可能的, 这时, 就存在避让问题。如果从全要素地形图出图考虑, 因为道路与居民地同在黑色版上, 河流在蓝色版上,所以避开道路要比避开河流更为优先, 所以, 最好是先避道路, 后避河流。但是, 如果要出一张与水系有关的专题图, 避开河流应比道路更为优先。因此, 在进行自动注记之前, 需根据应用的要求对压盖的优先级先给出一个综合的考虑。
</li>
<li><h4>屏幕输出与图纸输出</h4>
对于图纸输出, 注记参数应有更严格的规定;对于屏幕输出, 由于计算机屏幕输出可以方便地缩放、漫游, 注记的参数可以更为灵活处理, 可给出一个系统缺省值, 再提供方便的交互式手段让用户可以根据自己的需要进行设定和改变。
</li>
</ol>
<p>
</p>
<p>这么多纲纲条条……太恶心了。但是要做，没办法，硬着头皮来吧！
</p>
<p>关于算法，也有很多，什么神经网络，退火算法，看了看，似乎没看懂，而且也太复杂。不看，自己想！
</p>
<p>首先，标注需要考虑全部图层的情况。这里又不能压盖，那里又需要优先……没办法，干脆就全部统筹成一个标注图层来管理。在这个图层中统一分配位置，就可以同时考虑避让压盖问题等等。
</p>
<p>然而，虽然统一管理，具体操作上却需要分别处理。也就是需要分开点，线，面三种情况分别处理。而在分别处理的同时还需要注意各个部分的统一。
</p>
<p><b>考虑点图层标注。</b>基本思路是逐点插入标注。后面点的运气就看前面的点啦。具体操作还是跟栅格法一样，插入一个点，然后标注一个点，点的标注位置有8个。按照优先级排右，上，左，下，右上，左上，左下，右下。把标注形成的矩形按照这八个位置摆放，如果不压盖其他标签或者点，就确定这个位置，如果8个位置都有压盖或者不合适，就放弃这个点的标注，然后察看下一个点，依此类推。和点选栅格法不同的是，这次只需要矩形定位，所以只需要内存中建立数组就够了，不需要DC的支持。确定了一个标签定位，就把标签所覆盖的矩形区域内的各个象元值赋值为1(或者非0的其他值)。判断有无压盖就判断矩形所在区域内的象元值之和是否为0（数组初始化的时候每个象元都为0），为0就是无压盖，不为0就是有压盖。当然，为了做到不压盖数据点，第一步就是需要把点全部在内存数组中的位置赋值为非零值。
</p>
<p><b>考虑多边形图层标注。</b>基本思路也是逐点插入标注。做法和点图层的很像。不同的是，多边形标注不分位置优先，只用多边形的质心（暂时不考虑其他位置，如线状多边形的标注排列等等）。另外还需要注意面积大小问题。如果在绘制区域中，多边形面积小于一定数值，就不需要标注（如果标注了，那破碎地形会标注得很难看）
</p>
<p><b>线标注的问题十分复杂。</b>基本是因为线的排列是有走向的。标注需要沿着一定路径进行排列。而中文标注不比英文标注。ESRI的中文标注是沿线走向有一定旋转角度的。虽然英文看起来很专业，中文看起来就很难看。所以要做到把中文拆字，按照线的走向，进行无旋转的排列。另外线的走向判断也是一件很精细的事情，需要考虑非常多的细节，但是我现在先不考虑这么多，先挑线中最长位置最靠中的那段线段，按照那根线段的斜率进行延展以适应走向，进行标注排列。压盖问题和点以及多边形的处理方式类似。
</p>
<p><b>最后</b>还需要根据点线面的类型，进行优先级判断排列。我的做法是把所有标注和其标注位置以及标注样式都提取出来，然后把所有的标注排列都放在同一个内存数组区域中进行，这样就便于各层优先级判断以及避免各层互相压盖等等问题。这样就达到一种统一管理的效果。而重要地物的优先级别就由图层排列顺序来确定了。
</p>
<p>具体的实现请参看九形源代码geosings.core.LabelLayout，以及geosings.ui.gmap.LayerCanvas两个模块中的相关代码。
</p>
<hr /><!--"----------------------------------------"-->
<br />

<table id='etab'>
	<td id='etit'>geosings, 标注算法</td>
	<td id='ereta'><a href='../index.html'>返回主目录</a></td>
</table>

</body>
</html>

